package effectiveJava.reflect.OneZoreNine;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class Utils {

    /**
     * @see java泛型只存在与编译器,为什么这个工具类可以取得运行期的泛型参数呢？
     * todo 1. 那是因为该工具类只支持继承的泛型类，如果在 java 编译时已经确定泛型类的类型参数，那当然可以通过泛型获得了
     * todo 2. 对于例子中的 UserDao 编译器编译时就已经明确其参数类型，因此可以通过反射的方式获得其类型
     * todo 3. 父类泛型化，子类明确泛型参数，这样在编译时就已经明确泛型类型，然后通过反射读取相应的类型即可
     * @see 关键在于运行时确实无法获得泛型信息,但是通过父类泛型化,子类明确泛型类型,在编译时就已经明确泛型类型,自然可以“看似”动态获得
     * @param clz
     * @param <T>
     * @return
     */
    public static <T> Class<T> getGenericsType(Class clz) {
        Type type = clz.getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            ParameterizedType tp = (ParameterizedType) type;
            Type[] types = tp.getActualTypeArguments();
            if (types.length > 0 && types[0] instanceof Class) {

                return (Class<T>) types[0];
            }
        }
        return (Class<T>) Object.class;
    }

}
